package com.monkey.banana.game.shudu;


/**
 * Description: 九宫格数据控制
 * Author: Archur
 * Date: 2017-09-16
 * Time: 9:03
 */


public class Game {

    private static final String TAG = "Game";

    //初始化九宫格的数据
    private final String initStr =
            "362581479914237856785694231" +
                    "179462583823700614546813927" +
                    "431925768657148392298376145";

    //一维数组储存九宫格的所有数据(一维数组)
    private int[] shuduku = new int[9 * 9];

    //用于存储已经使用过的数据(三维数组)
    private int[][][] used = new int[9][9][];

    public Game() {
        shuduku = fromPuzzleString(initStr);
        calculateAllUsedTiles();
    }

    /**
     * 1 字符串一个个分离出来，存放至shudu数组中
     */
    public int[] fromPuzzleString(String str) {
        int[] shudu = new int[str.length()];

        for (int i = 0; i < str.length(); i++) {
            shudu[i] = str.charAt(i) - '0';
        }
        return shudu;
    }

    /**
     * 2-1 获取指定单元格的数字(有0)
     */
    private int getTitle(int x, int y) {
        return shuduku[x + 9 * y];
    }

    /**
     * 2-2 获取指定单元格的文本(0换为"")
     */
    public String getTileString(int x, int y) {
        int v = getTitle(x, y);
        if (0 == v) {
            return "";
        } else {
            return String.valueOf(v);
        }
    }

    /**
     * 3-1 计算每一个单元格不可用的数字
     */
    private void calculateAllUsedTiles() {
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                // 这里的 数组 赋值，只要 它们 加起来 是 三维 即可，假如是 四维 也一样
                used[i][j] = calculateUsedTiles(i, j);
            }
        }
    }

    /**
     * 3-2 计算指定单元格不可用的数字
     */
    public int[] calculateUsedTiles(int x, int y) {

        int[] c = new int[9];

        // 3-2-1 计算该单元格列上不可用数据
        for (int i = 0; i < 9; i++) {
            //该列上自己本身不计算
            if (i == y) continue;
            int t = getTitle(x, i);

            if (t != 0) c[t - 1] = t;
        }

        // 3-2-2 计算该单元格行上不可用数据
        for (int i = 0; i < 9; i++) {
            // 该行上自己本身不计算
            if (i == x) continue;

            int t = getTitle(i, y);

            if (t != 0) c[t - 1] = t;
        }

        // 3-2-3计算该单元格所在九宫格中不可用数据
        int startX = (x / 3) * 3;//0、3、6几种取值
        int startY = (y / 3) * 3;//0、3、6几种取值
        for (int i = startX; i < startX + 3; i++) {
            for (int j = startY; j < startY + 3; j++) {
                if (i == x && j == y) continue;
                int t = getTitle(i, j);
                if (t != 0) c[t - 1] = t;
            }
        }

        // 3-2-4 计算该单元格不可用数字的数量
        int nused = 0;
        for (int t : c) {
            if (t != 0)
                nused++;
        }
        //储存不可用数字的数组
        int[] c1 = new int[nused];

        // 为不可用数字的数组赋值
        nused = 0;
        for (int t : c) {
            if (t != 0) {
                c1[nused++] = t;
            }
        }

        // TODO: 2017/9/16 一旦该单元格有值,不可用数据为1-9

        return c1;
    }

    /**
     * 3-3 取出某个单元格中不可用的数
     */
    public int[] getUsedTilesByCoor(int x, int y) {
        return used[x][y];
    }

    /**
     * 4 把用户选的字，设置到shuduku数组中
     */
    public boolean setTileIfValid(int x, int y, int value) {
        // 取出某个单元格中 不可用的 数
        int tiles[] = getUsedTilesByCoor(x, y);

        if (value != 0) {
            for (int tile : tiles) {
                //如果用户选的数字和 “ 不可用数组” 里面的数字相同，则返回false，
                if (tile == value) {
                    return false;
                }
            }
        }

        shuduku[9 * y + x] = value;

        //每次修改之后都得 进行重新计算 不可用的值
        calculateAllUsedTiles();

        return true;
    }

}
